package com.guyu.plugin.doc;

import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Pattern;

@Slf4j
public class TagJavadocOpenApiCustomizer implements GlobalOpenApiCustomizer {

    private Predicate<String> snakeNameMatcher = Pattern.compile("^[a-zA-Z0-9-]+$").asPredicate();

    @Override
    public void customise(OpenAPI openApi) {
        log.info("TagJavadocOpenApi OpenApiCustomizer");
        // 把 controller上面的注释 生成TAG
        // 官方默认是把注释弄成了description，但是我们希望他的变成tag

        if (openApi.getTags() == null) {
            return;
        }

        List<Tag> tags = openApi.getTags();
        for (Tag tag : tags) {
            if (snakeNameMatcher.test(tag.getName()) && StrUtil.isNotEmpty(tag.getDescription())) {
                String newName = tag.getDescription();

                // 同步修改映射关系
                openApi.getPaths().forEach((s, pathItem) -> {
                    List<Operation> operations = new ArrayList<>();
                    addIfNotNull(operations, pathItem.getGet());
                    addIfNotNull(operations, pathItem.getDelete());
                    addIfNotNull(operations, pathItem.getDelete());
                    addIfNotNull(operations, pathItem.getOptions());
                    addIfNotNull(operations, pathItem.getPatch());
                    addIfNotNull(operations, pathItem.getPost());
                    addIfNotNull(operations, pathItem.getPut());
                    addIfNotNull(operations, pathItem.getTrace());

                    for (Operation operation : operations) {
                        for (int i = 0; i < operation.getTags().size(); i++) {
                            if (operation.getTags().get(i).equals(tag.getName())) {
                                operation.getTags().set(i, newName);
                            }
                        }
                    }

                });
                tag.name(newName);
            }
        }
    }

    private <T> void addIfNotNull(List<T> original, T itemsToAdd) {
        if (itemsToAdd != null) {
            original.add(itemsToAdd);
        }
    }
}
